######################################################################
# Time-stamp: <2005-08-29 10:50:02 ostolop>
#
# Package: EP::Core::Data::Parser::exp
#
# Expression Data Parser Classes
######################################################################
package EP::Core::Data::Parser::exp::affy;

use strict;
use base qw ( EP::Core::Data::Parser );

use EP::Config;
use EP::Common;
use EP::Common::General;
use EP::Common::Error qw ( :try );

use File::Temp qw ( tempdir );
use File::Spec;
use File::Basename;

use EP::Rclient;

# sub: parse_data
# processes the uploaded data and creates a corresponding entry in the database
sub parse_data {
  my $self = shift;
  my $data = {};

  if ( $self->{query}->param ( 'src_files' ) ne "" ) {
	my $tempceldir = "$EP::Config::h->{TMP}/" . $self->{epc}->{session}->id . ".CEL";
	warn "Got " . scalar <$tempceldir/*> . " (CEL?) files in $tempceldir.";
  } else {
	$data = $self->upload_data ();
	warn "Uploaded data size is: ", -s "$data->{data}";
  }

  my $cur_folder = $self->{epc}->{session}->current_folder;

  throw EP::Common::Error ( -value => CUD_NO_DATA_SUPPLIED ) if -z "$data->{data}";

  if ( $self->_process_uploaded_data ( $data ) ) {
    my ($dataset) = EP::Common::DBI->do_transaction (
     sub {
       my ($self) = @_;

       my $dataset = EP::Common::DBI::Dataset->create ({ name         => substr($data->{dataset_name}, 0, 72) . " : ". localtime,
							 description  => $self->{query}->param ( "dataset_description" ) . "",
							 type         => "affy",
							 species      => $data->{species},
							 folder       => $cur_folder->id,
							 ep_session      => $self->{epc}->{current_user}->session_only ? $self->{epc}->{session}->id : undef,
							 owner        => $self->{epc}->{current_user},
							 group_write  => 0,
							 group_read   => 1,
							 other_read   => 0
						       });

       $self->_write_dataset_data ( $dataset, $data ) or die "Failed to write the dataset data!";
       return $dataset;
     }, $self );

    $self->{epc}->{session}->status ( "Data set uploaded ..." );

    return $dataset;
  }

  die "Failed to process uploaded data.";
}

# sub: _process_uploaded_data
# Processes uploaded data (identifies file, reads in the related data, sets it up for further use)
# WRITE MORE HERE.
sub _process_uploaded_data
    {
    my $self = shift;
    my ( $data ) = @_;

    my $query = $self->{query};

    my $tempceldir = tempdir ( "CELTEMP-XXXXXX", CLEANUP => 0, UNLINK => 0, DIR => "$EP::Config::h->{TMP}" );
    chmod 0750, $tempceldir;

    if ( $query->param ( 'src_files' ) ne "" )
        {
        $tempceldir = "$EP::Config::h->{TMP}/" . $self->{epc}->{session}->id . ".CEL";
        }
    else
        {
        warn "We have '$data->{data}' uploaded";
        if ( "$data->{data}" =~ /(\.tar\.gz|\.tgz)$/i )
            {
            $self->{epc}->{session}->status("Unpacking the CEL archive (tar) ...");
            warn "Unpacking 'tar xzf $data->{data} --directory $tempceldir'";
            die "Could not unpack the archive" if EP::Common::General::system_call ( "tar xzf $data->{data} --directory $tempceldir" ) != 1;
            }
        elsif ( "$data->{data}" =~ /\.zip$/i )
            {
            $self->{epc}->{session}->status("Unpacking the CEL archive (zip) ...");
            die "Could not unpack the archive" if EP::Common::General::system_call ( "unzip $data->{data} -d $tempceldir" ) != 1;
            }
        elsif ( "$data->{data}" =~ /\.cel$/i )
            {
            my $mvout = system_call_with_output( "mv $data->{data} $tempceldir/" . basename($data->{data}) );
            die "Could not move the file into temporary directory" if $mvout;
            }
        else
            {
            die "The loader was unable to determine the format of the supplied file. Supported file suffixes: .cel, .zip, .tar, .tar.gz, .tgz";
            }
        }

    $self->{epc}->{session}->status ( "Reading in the CEL file(s) ..." );

    my $affydatafile = new File::Temp;
    my $affycols = new File::Temp;
    my $affyrows = new File::Temp ( UNLINK => 0 );
    my $species = $query->param('affy_species');

    EP::Rclient->R(<<__RCODE__);
app_root = "$EP::Config::h->{ROOT}";
source("$EP::Config::h->{ROOT}/cgi-lib/tmpl/R/ep.readaffy.tmpl.R");
ep.readaffy( tempceldir = "$tempceldir"
           , affydatafile = "$affydatafile"
           , affycols = "$affycols"
           , affyrows = "$affyrows"
           ,  species = "$species"
           );
__RCODE__

#  unlink $data->{data} if exists $data->{data};
#  unlink <$tempceldir/*>;
#  rmdir $tempceldir;

    $data->{affydata} = $affydatafile;
    $data->{affycols} = $affycols;
    $data->{affyrows} = $affyrows;
    $data->{species} = $species;

    return OK;
    }

# sub: _write_dataset_data
# Writes the data files for an expression dataset to the disk. It uses hash keys for row and column indexes.
sub _write_dataset_data {
  my $self = shift;
  my ( $dataset, $data ) = @_;
  local ( *COLUMNS, *ROWS );
  my (%seen);
  my $row = 0;

  my $folder   = $EP::Config::h->{EPNG_USRDATA_PATH} . "/" . $dataset->folder->location;
  my $filename = $dataset->filename;

  my $mvout = system_call_with_output ( "mv $data->{affydata} $folder/$filename.Rdata" );
  die "$mvout" if $mvout;

  $mvout = system_call_with_output ( "mv $data->{affycols} $folder/$filename.columns" );
  die "$mvout" if $mvout;

  warn "Want to mv $data->{affyrows} $folder/$filename.rows";
  $mvout = system_call_with_output ( "cp $data->{affyrows} $folder/$filename.rows" );
  die "$mvout" if $mvout;

  warn "Successfully written expression dataset $filename to folder $folder" if DEBUG;

  return OK;
}

1;
